package org.xtown.bingluo.xtieba.sync;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.Header;
import org.apache.http.message.BasicHeader;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.xtown.bingluo.xtieba.AhException.AhBaseException;
import org.xtown.bingluo.xtieba.db.XtiebaAuthorDb;
import org.xtown.bingluo.xtieba.db.XtiebaPostsDb;
import org.xtown.bingluo.xtieba.db.XtiebaPostsInfoDb;
import org.xtown.bingluo.xtieba.model.XtiebaAuthor;
import org.xtown.bingluo.xtieba.model.XtiebaPosts;
import org.xtown.bingluo.xtieba.model.XtiebaPostsInfo;
import org.xtown.bingluo.xtieba.net.HttpClientHelper;
import org.xtown.bingluo.xtieba.net.HttpResult;
import org.xtown.bingluo.xtieba.standby.Constants;
import org.xtown.bingluo.xtieba.utils.CRequest;
import org.xtown.bingluo.xtieba.utils.IOUtils;
import org.xtown.bingluo.xtieba.utils.LogUtlils;
import org.xtown.bingluo.xtieba.utils.MobileUtils;

import android.content.Context;
import android.os.AsyncTask;

public class CrawlSyncTask extends AsyncTask<SyncTaskInfo, Integer, Throwable> {

	private Context mContext;
	private ISyncListener mListener;
	private XtiebaPosts xtiebaPosts = null;
	private String baiduDomain = "wapp.baidu.com";

	private boolean mFullSync = false;
	private HttpClientHelper hc;
	private String localAvatar = "";
	private String internetAvatar;
	private XtiebaAuthor xtiebaAuthor;
	private String mUserAgent;

	public CrawlSyncTask(Context context, ISyncListener listener) {
		mContext = context;
		context.getContentResolver();
		mListener = listener;
		mUserAgent = MobileUtils.getUserAgent(context);
	}

	@Override
	protected Throwable doInBackground(SyncTaskInfo... arg0) {
		Throwable result = null;

		try {
			publishProgress(0, 0, 0);
			crawlExecutor(arg0[0]);
		} catch (AhBaseException e) {
			e.printStackTrace();
			result = e;
		}

		return result;
	}

	/**
	 * 
	 */
	private void crawlExecutor(SyncTaskInfo arg0) throws AhBaseException {
		ToTiebaQueryParameter obj = (ToTiebaQueryParameter) arg0.getData();
		String kzid = obj.kzid;
		int postsCount = obj.postsCount;
		Boolean isAdditional = obj.isAdditional;
		String see_lz = "1";
		int sleepTime = 1000 * 2;
		int done = 0;
		int pageSize = Constants.FOR_BAIDU_PAGE_SIZE;
		int cPageSize = 0;
		String baseUrl = "http://" + baiduDomain + "/m?kz=" + kzid + "&pbrn="
				+ pageSize + "&see_lz=" + see_lz + "&global=1&expand=1";

		// "http://wapp.baidu.com/m?kz=1793033379&see_lz=1&pn=0";
		Document doc = null;
		/************** 模拟登陆百度 http://wapp.baidu.com S ***************/
		hc = new HttpClientHelper(true);
		// HttpResult lr = hc.get(SESSION_INIT);// 目的是得到 csrfToken 类似
		// 拼装登录信息
		Map<String, String> data = new HashMap<String, String>();
		data.put("login_username", "修理如果");
		data.put("login_loginpass", "123456!");
		data.put("aaa", "登录");
		data.put("login", "yes");
		data.put("can_input", "0");
		data.put("u", "");
		// data.put("login_start_time", "1347847959");
		data.put("tpl", "bdIndex");
		data.put("pu", "");
		data.put("ssid", "");
		data.put("from", "");
		data.put("bd_page_type", "1");
		// data.put("uid", "wapp_1347847954115_112");
		data.put("type", "");
		hc.post("http://wappass.baidu.com/passport/", data,
				setWappassBaiduComHeader());
		/************** 模拟登陆百度 http://wapp.baidu.com E ***************/
		publishProgress(1, 0, 0);
		// hc.pringCookieAll();
		if (isAdditional) {
			done = postsCount / pageSize;
		}
		LogUtlils.println("url="+baseUrl + "&pn=" + (done * pageSize));
		HttpResult lr2 = hc.get(baseUrl + "&pn=" + (done * pageSize));
		doc = Jsoup.parse(lr2.getHtml());
//		if (isAdditional) {
//			Element tmpElement2 = doc.select("div.d").first();
//			if (tmpElement2 == null) {
//				throw new AhBaseException(
//						"抓取失败，可能是当前您网络不稳定，也可能是百度抓太频了把您给屏了，过会儿再来，休息一下。");
//			}
//			Elements elements = tmpElement2.select("div.i");
//			cPageSize = elements.size();
//			done = postsCount / pageSize;
//			LogUtlils.println("done==" + done + "::postsCount=" + postsCount);
//			if (done > 1) {
//				lr2 = hc.get(baseUrl + "&pn=" + (done * pageSize));
//				doc = Jsoup.parse(lr2.getHtml());
//			} else {
//				done = 0;
//			}
//		}
		parseIntoDb(doc, kzid);

		Element tmpElement = doc.select("div.d").first();
		if (tmpElement == null) {
			throw new AhBaseException(
					"抓取失败，可能是当前您网络不稳定，也可能是百度抓太频了把您给屏了，过会儿再来，休息一下。");
		}
		// 获取总页数
		String pnum = tmpElement.select("input[name=pnum]").val();
		int pageTotal = 1;
		try {
			pageTotal = Integer.valueOf(pnum);
			if (pageTotal == 1) {
				pageTotal = done + 1;
			}
		} catch (NumberFormatException e) {
			e.printStackTrace();
			pageTotal = 1;
		}
		System.out.println(pageTotal);
		// 测试的时候只抓5页
		if (Constants.DEBUG && pageTotal > 5) {
			pageTotal = 5;
		}
		// 第一页抓取完毕
		LogUtlils.println("done==" + done + "::pageTotal=" + pageTotal);
		publishProgress(2, done + 1, pageTotal);
		mySleep(sleepTime);
		// if (true)
		// return;
		for (done++; done < pageTotal; done++) {
			LogUtlils.println("done==" + done + "::pageTotal=" + pageTotal);
			publishProgress(2, done + 1, pageTotal);
			if (isCancelled()) {
				break;
			}
			lr2 = hc.get(baseUrl + "&pn=" + (done * pageSize));
			doc = Jsoup.parse(lr2.getHtml());
			parseIntoDb(doc, kzid);
			mySleep(sleepTime);
		}
	}

	private void parseIntoDb(Document doc, String kzid) throws AhBaseException {
		LogUtlils.println(doc.html());
		// 标题
		String title = doc.title();
		String author = "";
		int floorNo;
		String content = "";
		String time = "";
		int posts_created_at;
		int created_at;
		int updated_at;
		created_at = updated_at = (int) (System.currentTimeMillis() / 1000);

		XtiebaPostsInfo xtiebaPostsInfo = null;
		List<XtiebaPostsInfo> xtiebaPostsInfos = new ArrayList<XtiebaPostsInfo>();

		Element tmpElement = doc.select("div.d").first();
		if (tmpElement == null) {
			LogUtlils.println(doc.toString());
			throw new AhBaseException("抓取失败");
		}
		Elements elements = tmpElement.select("div.i");
		for (Element element : elements) {
			// 作者
			Element e = element.select("span.g a").first();
			if (e == null) {
				throw new AhBaseException("得到author失败");
			}
			author = e.text();
			if (localAvatar.equals("")) {
				// 抓头像
				String userImg = "";
				String userHome = e.attr("href");

				LogUtlils.println(userHome);
				if (!userHome.equals("")) {
					char c = userHome.charAt(0);
					if (c == '/') {
						userImg = "http://" + baiduDomain + userHome;
					}
					if (!userImg.equals("")) {
						HttpResult lr2 = hc.get(userImg);
						Document docTmp = Jsoup.parse(lr2.getHtml());
						Element eTmp = docTmp.select("div.bc img[alt=头像]")
								.first();
						if (eTmp != null && !eTmp.attr("src").equals("")) {
							Map<String, String> mapRequest = CRequest
									.URLRequest(eTmp.attr("src"));
							if (mapRequest.containsKey("src")
									&& !mapRequest.get("src").equals("")) {
								try {
									String urlTmp = mapRequest.get("src");
									internetAvatar = URLDecoder.decode(urlTmp,
											"UTF-8");
									if (!internetAvatar.equals("")) {
										localAvatar = IOUtils
												.makeLocalAvatarPath(
														mContext,
														author
																+ Constants.AUTHOR_AVATAR_SUFFIX);
										LogUtlils.println(internetAvatar);
										IOUtils.getBitmapFromUrl(mContext,
												internetAvatar, localAvatar);
										xtiebaAuthor = new XtiebaAuthor(0,
												userImg, author, localAvatar,
												internetAvatar, created_at,
												updated_at);
										LogUtlils.println(xtiebaAuthor
												.toString());
										XtiebaAuthorDb xtiebaAuthorDb = XtiebaAuthorDb
												.getNetInstance(mContext);
										xtiebaAuthor = xtiebaAuthorDb
												.save(xtiebaAuthor);
										LogUtlils.println(xtiebaAuthor
												.toString());
										xtiebaAuthorDb.close();
									}
								} catch (UnsupportedEncodingException e1) {
									e1.printStackTrace();
								}
							}
						}
					}
				}
			}

			String s1 = element.children().text();
			s1 = s1.trim();
			s1 = s1.replaceAll("图", "");
			LogUtlils.println(s1);
			s1 = s1.replaceAll(" +", " ");
			LogUtlils.println(s1);
			String escapedS1 = Pattern.quote(s1);
			String s2 = element.text();
			LogUtlils.println(s2);
			s2 = s2.replaceAll("\u00A0", " ");
			s2 = s2.replaceAll(" +", " ");
			String r = s2.replaceAll(escapedS1, "");
			LogUtlils.println(r);
			// if (true) continue;

			// 楼层数和帖子内容
			Pattern pattern = Pattern.compile("(\\d+)楼\\.(.*)");
			Matcher matcher = pattern.matcher(r);
			if (matcher.find()) {
				floorNo = Integer.valueOf(matcher.group(1).trim());
				content = matcher.group(2).trim();
			} else {
				throw new AhBaseException("得到楼层数和帖子内容失败");
			}
			LogUtlils.println("floorNo=" + floorNo);
			LogUtlils.println("content=" + content);

			// 日期
			pattern = Pattern
					.compile("((\\d{4,4}-)?(\\d{1,2}-\\d{1,2})?( \\d\\d:\\d\\d)?)");
			matcher = pattern.matcher(s1);
			if (matcher.find()) {
				time = matcher.group(1);
				if (matcher.group(4) == null) {
					time += " 00:00";
				}
				if (matcher.group(3) == null) {
					time = (Calendar.getInstance().get(Calendar.MONTH) + 1)
							+ "-"
							+ Calendar.getInstance().get(Calendar.DAY_OF_MONTH)
							+ time;
				}
				if (matcher.group(2) == null) {
					Calendar cal = Calendar.getInstance();
					time = cal.get(Calendar.YEAR) + "-" + time;
				}
				int timeStemp = 0;
				try {
					SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
							"yyyy-MM-dd hh:mm");
					Date date = simpleDateFormat.parse(time);
					timeStemp = (int) (date.getTime() / 1000);
				} catch (ParseException e2) {
					e2.printStackTrace();
				}
				posts_created_at = timeStemp;
			} else {
				throw new AhBaseException("得到帖子发表日期失败");
			}

			if (xtiebaPosts == null) {
				xtiebaPosts = new XtiebaPosts(0, kzid, title, author,
						posts_created_at, created_at, updated_at);
				XtiebaPostsDb xtiebaPostsDb = XtiebaPostsDb
						.getNetInstance(mContext);
				xtiebaPosts = xtiebaPostsDb.save(xtiebaPosts);
				xtiebaPostsDb.close();
			}
			if (xtiebaPosts == null || xtiebaPosts.id == 0) {
				throw new AhBaseException("本地数据库帖子生成失败");
			}
			xtiebaPostsInfo = new XtiebaPostsInfo(0, xtiebaPosts.id, floorNo,
					content, author, posts_created_at, created_at, updated_at);
			xtiebaPostsInfos.add(xtiebaPostsInfo);
		}
		if (xtiebaPostsInfos != null && !xtiebaPostsInfos.isEmpty()) {
			XtiebaPostsInfoDb xtiebaPostsInfoDb = new XtiebaPostsInfoDb(
					mContext);
			xtiebaPostsInfoDb.save(xtiebaPostsInfos);
			xtiebaPostsInfoDb.close();
		}
	}

	/**
	 * @param sleepTime
	 * @throws AhBaseException
	 */
	private void mySleep(int sleepTime) throws AhBaseException {
		try {
			Thread.sleep(sleepTime);
		} catch (InterruptedException e) {
			e.printStackTrace();
			throw new AhBaseException("悲剧休眠异常", e);
		}
	}

	public Header[] setWappassBaiduComHeader() {
		LogUtlils.println("mUserAgent=" + mUserAgent);
		if (mUserAgent.equals("")) {
			mUserAgent = "Mozilla/5.0 (Linux; U; Android 2.1-update1; zh-cn; Dext Build/ERD79) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17";
		}
		Header[] result = {
				new BasicHeader("Host", "wappass.baidu.com"),
				new BasicHeader("User-Agent", mUserAgent),
				new BasicHeader("Accept",
						"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"),
				new BasicHeader("Accept-Language", "	zh-cn,zh;q=0.5"),
				new BasicHeader("Accept-Encoding", "gzip, deflate"),
				new BasicHeader("Accept-Charset", "GB2312,utf-8;q=0.7,*;q=0.7"),
				new BasicHeader("Keep-Alive", "115"),
				new BasicHeader("Connection", "Keep-Alive"),
				new BasicHeader("Referer", "http://wapp.baidu.com/"),
				new BasicHeader("Cache-Control", "max-age=0"),

		};
		return result;
	}

	@Override
	protected void onCancelled() {
		mListener.onSyncCancelled();
		super.onCancelled();
	}

	@Override
	protected void onProgressUpdate(Integer... values) {
		mListener.onSyncProgress(values[0], values[1], values[2]);
	}

	@Override
	protected void onPostExecute(Throwable result) {
		mListener.onSyncEnd(result);
	}

	public boolean isFullSync() {
		return mFullSync;
	}

}
